package com.szxy.sso.service.impl;

import com.szxy.mapper.TbUserMapper;
import com.szxy.pojo.TbUser;
import com.szxy.pojo.TbUserExample;
import com.szxy.sso.feign.CommonRedisFeignClient;
import com.szxy.sso.service.SSOService;
import com.szxy.utils.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * @Auther:zwer
 * @Date:2019/9/12 15:22
 * @Description:com.szxy.sso.service
 * @Version:1.0
 **/
@Service
public class SSOServiceImpl implements SSOService {

    @Autowired
    private TbUserMapper userMapper;
    @Autowired
    private CommonRedisFeignClient commonRedisFeignClient;
    @Value("${cookie_front_user_token}")
    private String cookie_front_user_token;

    @Value("${cookie_cart_name}")
    private String cookie_cart_name;

    /**
     * 校验用户信息
     * @param checkValue  需要被校验的 value
     * @param checkFlag   1. 表示校验用户名  2. 表示校验手机名是否存在
     * @return
     */
    @Override
    public Result checkUserInfo(String checkValue, int checkFlag) {
        TbUserExample example = new TbUserExample();
        TbUserExample.Criteria criteria = example.createCriteria();
        if(checkFlag == 1){// 校验用户名
            criteria.andUsernameEqualTo(checkValue);
        }else if(checkFlag == 2){// 手机号
            criteria.andPhoneEqualTo(checkValue);
        }
        int rows = this.userMapper.countByExample(example);
        if(rows == 0){
            return Result.ok(checkValue);
        }
        return  Result.error("数据不可用");
    }

    /**
     * 用户注册
     * @param user
     * @return
     */
    @Override
    public Result userRegister(TbUser user) {
        // 密码加密
        user.setPassword(MD5Utils.digest(user.getPassword()));
        // 补全数据
        user.setCreated(new Date());
        user.setUpdated(new Date());
        // 注册
        this.userMapper.insert(user);
        return Result.ok();
    }

    /**
     * 用户登录
     * @param user
     * @param request
     * @param response
     * @return
     */
    @Override
    public Result userLogin(TbUser user, HttpServletRequest request, HttpServletResponse response) {
            // 根据用户名查询对应的用户信息
            TbUser tbUser = this.login(user);
            if(tbUser != null && tbUser.getPassword().equals(user.getPassword())){
                // 采用 UUID 的方式生成 Token
                String token = UUID.randomUUID().toString();
                // 将用户数据放入 Redis 中
                Integer flag = this.userInfoToRedis(tbUser, token);
                if(flag == 500){
                    return Result.error("登录失败");
                }
                // 创建 UserToken 对象，返回给客户端响应
                UserToken userToken = new UserToken();
                userToken.setUserid(tbUser.getId());
                userToken.setUsername(tbUser.getUsername());
                userToken.setToken(token);
                // 将临时购物车中商品添加到永久购物车-->同步购物车
                this.syncCart(tbUser.getId().toString(),request);
                // 将临时购物车删除
                this.deleteCookiesCart(request,response);
                return  Result.ok(userToken);
            }
            return Result.error("用户密码错误");
    }

    // 将临时购物车删除
    private void deleteCookiesCart(HttpServletRequest request, HttpServletResponse response){
        CookieUtils.deleteCookie(request,response,this.cookie_cart_name);
    }

    // 同步到 Redis 购物车中
    private void syncCart(String userId, HttpServletRequest request){
        // 查询临时购物车
        Map<String, CartItem> tempCart = this.getCookieCart(request);
        // 查询永久购物车
        Map<String, CartItem> cart = this.getRedisCart(userId);
        for(String key : tempCart.keySet()){
            if(cart.containsKey(key)){
                cart.remove(key);
            }
        }
        // 将临时购物车添加永久购物车中
        cart.putAll(tempCart);
        // 将永久购物中重新放入 Redis 中
        this.addCartToRedis(cart, userId);
    }

    // 查询临时购物车
    private Map<String, CartItem> getCookieCart(HttpServletRequest request) {
        Map<String, CartItem> cart = null;
        try {
            // 获取当前 Cookie 中购物车 Json 数据
            String cartJson = CookieUtils.getCookieValue(request, this.cookie_cart_name, true);
            if (cartJson != null) {
                // 将 cartJson 转为 Map 对象
                cart = JsonUtils.jsonToMap(cartJson, CartItem.class);
                if (cart != null) return cart;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<String, CartItem>();
    }

    //2. 获取当前购物车
    private Map<String, CartItem> getRedisCart(String userId) {
        try {
            Map<String, CartItem> map =
                    this.commonRedisFeignClient.selectCartByUserId(userId);
            if (map != null) {
                return map;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<String, CartItem>();
    }

    //4. 将购物车放入 Redis 缓存中
    private void addCartToRedis(Map<String, CartItem> cart, String userId) {
        HashMap<String, Object> map = new HashMap<>();
        map.put("userId", userId);
        map.put("cart", cart);
        this.commonRedisFeignClient.insertToCart(map);
    }
    
    /**
     * 根据用户名查询对应的用户信息
     * @param user
     * @return
     */
    private TbUser login(TbUser user){
        // 将表单传递过来的密码加密
        user.setPassword(MD5Utils.digest(user.getPassword()));
        TbUserExample example = new TbUserExample();
        TbUserExample.Criteria criteria = example.createCriteria();
        // where username = ?
        criteria.andUsernameEqualTo(user.getUsername());
        List<TbUser> userList = this.userMapper.selectByExample(example);
        if(userList != null && userList.size() >0) {
            TbUser tbUser = userList.get(0);
            return tbUser;
        }else{
            return null;
        }
    }

    /**
     * 将用户信息保存到 Redis 缓存中
     * @param tbUser
     * @param token
     * @return
     */
    private Integer userInfoToRedis(TbUser tbUser, String token){
        try {
            // 将 userToken 对象放入 Redis 缓存中
            this.commonRedisFeignClient.insertUserToken(tbUser,token);
            return 200;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 500;
    }

    @Override
    public Result logOut(String token, HttpServletRequest request, HttpServletResponse response) {
        try {
            //从 Redis 数据库中移除用户 Token 信息
            this.commonRedisFeignClient.removeUserToken(token);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // CookieUtils.deleteCookie(request,response,this.cookie_front_user_token);
        return Result.ok();
    }
}
